home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c-part2 / 12594 < prev    next >
Encoding:
Internet Message Format  |  1996-08-05  |  3.1 KB

  1. Path: mail2news.demon.co.uk!genesis.demon.co.uk
  2. From: Lawrence Kirby <fred@genesis.demon.co.uk>
  3. Newsgroups: comp.lang.c
  4. Subject: Re: casting const
  5. Date: Mon, 01 Apr 96 20:43:04 GMT
  6. Organization: none
  7. Message-ID: <828391384snz@genesis.demon.co.uk>
  8. References: <4jf4f5$3aa@news.aladdin.co.uk>
  9. Reply-To: fred@genesis.demon.co.uk
  10. X-NNTP-Posting-Host: genesis.demon.co.uk
  11. X-Newsreader: Demon Internet Simple News v1.27
  12. X-Mail2News-Path: genesis.demon.co.uk
  13.  
  14. In article <4jf4f5$3aa@news.aladdin.co.uk>
  15.            cats@aladdin.co.uk "Rob Catling" writes:
  16.  
  17. >
  18. >I was wondering why you could pass a char * value as an argument to
  19. >func(const char *) with no problem, but passing char ** value to 
  20. >func(const char **) gives a compiler warning (unless you cast it).
  21.  
  22. You have to consider what const gives you. It is basically a promise that
  23. something won't be modified through an lvalue derived from the declaration.
  24. Importantly you also get some verification of this from the compiler which
  25. can only be bypassed using casting. The problem is that if the language
  26. allowed assignment of a char ** to a const char ** (or similarly passing
  27. a char ** argument to a const char ** parameter) you could bypass this
  28. guarantee without either a compiler diagnostic or a cast. Consider:
  29.  
  30.     const char c, *cp, **cpp;
  31.     char     *p, **pp;
  32.  
  33.     cp = &c;
  34.  
  35.     pp = &p;      /* Create our (char **) value - the address of p */
  36.  
  37.     cpp = pp;     /* The illegal step - assign char ** to const char **
  38.                      cpp now points to p. */
  39.  
  40.     *cpp = cp;    /* Assign a (const char *) to a (const char *) which is
  41.                      legal. We've now managed to assign a const char *
  42.                      value to p by creating an lvalue (i.e. *cpp) that
  43.                      doesn't match the object */
  44.  
  45.     *p = 1;       /* And c has now been modified */
  46.  
  47.  
  48. >The comp.lang.c FAQ was the only place that told me why I had to cast a
  49. > function
  50. >argument to (const **), however I'm still wondering:
  51. >
  52. >1) how was this pieced together from the references? ANSI C ref and H&S failed
  53. >   to illuminate this for me.
  54.  
  55. ANSI 6.3.16.1 has a set of constraints, one of which is required to hold. The
  56. only one relevant here is:
  57.  
  58. " - both operands are pointers to qualified or unqualified versions of
  59.     compatible types, and the type pointed to by the left has all the
  60.     qualifiers of the type pointed to by the right;"
  61.  
  62. So (using the definitions above):
  63.  
  64.     cp = p;
  65.  
  66. is fine because char is compatible with itself and const char has every
  67. qualifer that char has (none on this case).
  68.  
  69.     cpp = pp;
  70.  
  71. is illegal because cpp is a pointer to const char * and pp is a pointer
  72. to char * - const char * and char * are incompatible types.
  73.  
  74. >2) is this really an elegant language feature or a practical kludge ?
  75.  
  76. It is nearly an elegant feature. The problem is that C doesn't allow
  77. you to assign (char **) to (const char *const *) which is safe. The C++
  78. rules do allow it and hopefully the next major C language revision will
  79. fix this.
  80.  
  81. -- 
  82. -----------------------------------------
  83. Lawrence Kirby | fred@genesis.demon.co.uk
  84. Wilts, England | 70734.126@compuserve.com
  85. -----------------------------------------
  86.